home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / usr / share / initramfs-tools / hooks / cryptroot < prev    next >
Encoding:
Text File  |  2011-03-11  |  12.1 KB  |  537 lines

  1. #!/bin/sh
  2.  
  3. PREREQ=""
  4.  
  5. prereqs()
  6. {
  7.     echo "$PREREQ"
  8. }
  9.  
  10. case $1 in
  11. prereqs)
  12.     prereqs
  13.     exit 0
  14.     ;;
  15. esac
  16.  
  17. . /usr/share/initramfs-tools/hook-functions
  18.  
  19. get_root_device() {
  20.     local device mount type options dump pass
  21.  
  22.     if [ ! -r /etc/fstab ]; then
  23.         return 1
  24.     fi
  25.  
  26.     grep -s '^[^#]' /etc/fstab | \
  27.     while read device mount type options dump pass; do
  28.         if [ "$mount" = "/" ]; then
  29.             device=$(canonical_device "$device") || return 0
  30.             echo "$device"
  31.             return
  32.         fi
  33.     done
  34. }
  35.  
  36. get_resume_devices() {
  37.     local device opt count dupe candidates devices
  38.     candidates=""
  39.  
  40.     # First, get a list of potential resume devices
  41.  
  42.     # uswsusp
  43.     if [ -e /etc/uswsusp.conf ]; then
  44.         device=$(sed -rn 's/^resume device[[:space:]]*[:=][[:space:]]*// p' /etc/uswsusp.conf)
  45.         if [ -n "$device" ]; then
  46.             candidates="$candidates $device"
  47.         fi
  48.     fi
  49.  
  50.     # uswsusp - again...
  51.     if [ -e /etc/suspend.conf ]; then
  52.         device=$(sed -rn 's/^resume device[[:space:]]*[:=][[:space:]]*// p' /etc/suspend.conf)
  53.         if [ -n "$device" ]; then
  54.             candidates="$candidates $device"
  55.         fi
  56.     fi
  57.  
  58.     # regular swsusp
  59.     for opt in $(cat /proc/cmdline); do
  60.         case $opt in
  61.         resume=*)
  62.             device="${opt#resume=}"
  63.             candidates="$candidates $device"
  64.             ;;
  65.         esac
  66.     done
  67.  
  68.     # initramfs-tools
  69.     if [ -e /etc/initramfs-tools/conf.d/resume ]; then
  70.         device=$(sed -rn 's/^RESUME[[:space:]]*=[[:space:]]*// p' /etc/initramfs-tools/conf.d/resume)
  71.         if [ -n "$device" ]; then
  72.             candidates="$candidates $device"
  73.         fi
  74.     fi
  75.  
  76.     # Now check the sanity of all candidates
  77.     devices=""
  78.     count=0
  79.     for device in $candidates; do
  80.         # Weed out clever defaults
  81.         if [ "$device" = "<path_to_resume_device_file>" ]; then
  82.             continue
  83.         fi
  84.  
  85.         # Detect devices required by decrypt_derived
  86.         derived="$(grep "^${device#/dev/mapper/}\b.*decrypt_derived" /etc/crypttab 2>/dev/null | awk '{print $3}')"
  87.         if [ -n "$derived" ]; then
  88.             if grep -q "^$derived" /etc/crypttab; then
  89.                 candidates="$candidates /dev/mapper/$derived"
  90.             else
  91.                 echo "cryptsetup: WARNING: decrypt_derived device $derived not found in crypttab" >&2
  92.             fi
  93.         fi
  94.  
  95.         device=$(canonical_device "$device") || return 0
  96.  
  97.         # Weed out duplicates
  98.         dupe=0
  99.         for opt in $devices; do
  100.             if [ "$device" = "$opt" ]; then
  101.                 dupe=1
  102.             fi
  103.         done
  104.         if [ $dupe -eq 1 ]; then
  105.             continue
  106.         fi
  107.  
  108.         # This device seems ok
  109.         devices="$devices $device"
  110.         count=$(( $count + 1 ))
  111.     done
  112.  
  113.     if [ $count -gt 1 ]; then
  114.         echo "cryptsetup: WARNING: found more than one resume device candidate:" >&2
  115.         for device in $devices; do
  116.             echo "                     $device" >&2
  117.         done
  118.     fi
  119.  
  120.     if [ $count -gt 0 ]; then
  121.         echo $devices
  122.     fi
  123.  
  124.     return 0
  125. }
  126.  
  127. node_is_in_crypttab() {
  128.     local node
  129.     node="$1"
  130.  
  131.     grep -q "^$node\b" /etc/crypttab
  132.     return $?
  133. }
  134.  
  135. get_lvm_deps() {
  136.     local node deps maj min depnode
  137.     node="$1"
  138.  
  139.     if [ -z $node ]; then
  140.         echo "cryptsetup: WARNING: get_lvm_deps - invalid arguments" >&2
  141.         return 1
  142.     fi
  143.  
  144.     if ! deps=$(dmsetup deps "$node" 2> /dev/null | sed 's/[^:]*: *//;s/[ (]//g;s/)/ /g'); then
  145.         echo "cryptsetup: WARNING: failed to find deps for $node" >&2
  146.         return 1
  147.     fi
  148.  
  149.     # We should now have a list of major,minor pairs, e.g. "3,2 3,3"
  150.     for dep in $deps; do
  151.         maj=$(echo ${dep%,*} | sed -e "s/^[ \t]*//g")
  152.         min=$(echo ${dep#*,} | sed -e "s/[ \t]*$//g")
  153.         depnode=$(dmsetup ls | sed -n "s/\\([^ ]*\\) *($maj, $min)/\\1/p" | sed -e "s/[ \t]*$//")
  154.         if [ -z "$depnode" ]; then
  155.             continue
  156.         fi
  157.         if [ "$(dmsetup table "$depnode" 2> /dev/null | cut -d' ' -f3)" != "crypt" ]; then
  158.             get_lvm_deps "$depnode"
  159.             continue
  160.         fi
  161.         echo "$depnode"
  162.     done
  163.  
  164.     return 0
  165. }
  166.  
  167. get_device_opts() {
  168.     local target source link extraopts rootopts opt
  169.     target="$1"
  170.     extraopts="$2"
  171.     KEYSCRIPT=""
  172.     OPTIONS=""
  173.  
  174.     if [ -z "$target" ]; then
  175.         echo "cryptsetup: WARNING: get_device_opts - invalid arguments" >&2
  176.         return 1
  177.     fi
  178.  
  179.     opt=$( grep "^$target\b" /etc/crypttab | head -1 | sed 's/[[:space:]]\+/ /g' )
  180.     source=$( echo $opt | cut -d " " -f2 )
  181.     key=$( echo $opt | cut -d " " -f3 )
  182.     rootopts=$( echo $opt | cut -d " " -f4- )
  183.  
  184.     if [ -z "$opt" ] || [ -z "$source" ] || [ -z "$key" ] || [ -z "$rootopts" ]; then
  185.         echo "cryptsetup: WARNING: invalid line in /etc/crypttab - $opt" >&2
  186.         return 1
  187.     fi
  188.  
  189.     # Sanity checks for $source
  190.     if [ -h "$source" ]; then
  191.         link=$(readlink -nqe "$source")
  192.         if [ -z "$link" ]; then
  193.             echo "cryptsetup: WARNING: $source is a dangling symlink" >&2
  194.             return 1
  195.         fi
  196.  
  197.         if [ "$link" != "${link#/dev/mapper/}" ]; then
  198.             echo "cryptsetup: NOTE: using $link instead of $source for $target" >&2
  199.             source="$link"
  200.         fi
  201.     fi
  202.  
  203.     # Sanity checks for $key
  204.     if [ "$key" = "/dev/random" ] || [ "$key" = "/dev/urandom" ]; then
  205.         echo "cryptsetup: WARNING: target $target has a random key, skipped" >&2
  206.         return 1
  207.     fi
  208.  
  209.     if [ -n "$extraopts" ]; then
  210.         rootopts="$extraopts,$rootopts"
  211.     fi
  212.  
  213.     # We have all the basic options, let's go trough them
  214.     OPTIONS="target=$target,source=$source,key=$key"
  215.     local IFS=", "
  216.     unset HASH_FOUND
  217.     unset LUKS_FOUND
  218.     for opt in $rootopts; do
  219.         case $opt in
  220.             cipher=*)
  221.                 OPTIONS="$OPTIONS,$opt"
  222.                 ;;
  223.             hash=*)
  224.                 OPTIONS="$OPTIONS,$opt"
  225.                 HASH_FOUND=1
  226.                 ;;
  227.             size=*)
  228.                 OPTIONS="$OPTIONS,$opt"
  229.                 ;;
  230.             lvm=*)
  231.                 OPTIONS="$OPTIONS,$opt"
  232.                 ;;
  233.             keyscript=*)
  234.                 opt=${opt#keyscript=}
  235.                 if [ ! -x "/lib/cryptsetup/scripts/$opt" ] && [ ! -x "$opt" ]; then
  236.                     echo "cryptsetup: WARNING: target $target has an invalid keyscript, skipped" >&2
  237.                     return 1
  238.                 fi
  239.                 KEYSCRIPT="$opt"
  240.                 OPTIONS="$OPTIONS,keyscript=/lib/cryptsetup/scripts/$(basename "$opt")"
  241.                 ;;
  242.             tries=*)
  243.                 OPTIONS="$OPTIONS,$opt"
  244.                 ;;
  245.             rootdev)
  246.                 OPTIONS="$OPTIONS,$opt"
  247.                 ;;
  248.             luks)
  249.                 LUKS_FOUND=1
  250.                 ;;
  251.             *)
  252.                 # Presumably a non-supported option
  253.                 ;;
  254.         esac
  255.     done
  256.  
  257.     # Warn for missing hash option, unless we have a LUKS partition
  258.     if [ -z "$HASH_FOUND" ] && [ -z "$LUKS_FOUND" ]; then
  259.         echo "WARNING: Option hash missing in crypttab for target $target, assuming ripemd160." >&2
  260.         echo "         If this is wrong, this initramfs image will not boot." >&2
  261.         echo "         Please read /usr/share/doc/cryptsetup/README.initramfs.gz and add" >&2
  262.         echo "         the correct hash option to your /etc/crypttab."  >&2
  263.     fi
  264.  
  265.     # If keyscript is set, the "key" is just an argument to the script
  266.     if [ "$key" != "none" ] && [ -z "$KEYSCRIPT" ]; then
  267.         echo "cryptsetup: WARNING: target $target uses a key file, skipped" >&2
  268.         return 1
  269.     fi
  270. }
  271.  
  272. get_device_modules() {
  273.     local node value cipher blockcipher ivhash
  274.     node="$1"
  275.  
  276.     # Check the ciphers used by the active root mapping
  277.     value=$(dmsetup table "$node" | cut -d " " -f4)
  278.     cipher=$(echo "$value" | cut -d ":" -f1 | cut -d "-" -f1)
  279.     blockcipher=$(echo "$value" | cut -d ":" -f1 | cut -d "-" -f2)
  280.     ivhash=$(echo "$value" | cut -d ":" -s -f2)
  281.  
  282.     if [ -n "$cipher" ]; then
  283.         echo "$cipher"
  284.     else
  285.         return 1
  286.     fi
  287.  
  288.     if [ -n "$blockcipher" ] && [ "$blockcipher" != "plain" ]; then
  289.         echo "$blockcipher"
  290.     fi
  291.  
  292.     if [ -n "$ivhash" ] && [ "$ivhash" != "plain" ]; then
  293.         echo "$ivhash"
  294.     fi
  295.     return 0
  296. }
  297.  
  298. canonical_device() {
  299.     local dev altdev original
  300.     dev="$1"
  301.  
  302.     altdev="${dev#LABEL=}"
  303.     if [ "$altdev" != "$dev" ]; then
  304.         dev="/dev/disk/by-label/$altdev"
  305.     fi
  306.  
  307.     altdev="${dev#UUID=}"
  308.     if [ "$altdev" != "$dev" ]; then
  309.         dev="/dev/disk/by-uuid/$altdev"
  310.     fi
  311.  
  312.     original="$dev"
  313.     if [ -h "$dev" ]; then
  314.         dev=$(readlink -e "$dev")
  315.     fi
  316.  
  317.     if [ "x${dev%/dev/dm-*}" = "x" ]; then
  318.         # try to detect corresponding symlink in /dev/mapper/
  319.         for dmdev in /dev/mapper/*; do
  320.             if [ "$(readlink -e "$dmdev")" = "$dev" ]; then
  321.                 dev="$dmdev"
  322.             fi
  323.         done
  324.     fi
  325.  
  326.     altdev="${dev#/dev/mapper/}"
  327.     if [ "$altdev" != "$dev" ]; then
  328.         echo "$altdev"
  329.         return 0
  330.     elif [ "x${original%/dev/disk/by-*/*}" = "x" ]; then
  331.         # support crypttab UUID/LABEL entries
  332.         # this is a /dev/disk/by-*/ path so return just the 'basename'
  333.         echo "${original##/dev/disk/by-*/}"
  334.         return 0
  335.     fi
  336.  
  337.     echo "cryptsetup: WARNING: failed to detect canonical device of $original" >&2
  338.     return 1
  339. }
  340.  
  341. add_device() {
  342.     local node nodes opts lastopts i count
  343.     nodes="$1"
  344.     opts=""     # Applied to all nodes
  345.     lastopts="" # Applied to last node
  346.  
  347.     if [ -z "$nodes" ]; then
  348.         return 0
  349.     fi
  350.  
  351.     # Flag root device
  352.     if [ "$nodes" = "$rootdev" ]; then
  353.         if [ -z "$opts" ]; then
  354.             opts="rootdev"
  355.         else
  356.             opts="$opts,rootdev"
  357.         fi
  358.     fi
  359.  
  360.     # Check that it is a node under /dev/mapper/
  361.     # nodes=$(canonical_device "$nodes") || return 0
  362.  
  363.     # Can we find this node in crypttab
  364.     if ! node_is_in_crypttab "$nodes"; then
  365.         # dm node but not in crypttab, is it a lvm device backed by dm-crypt nodes?
  366.         lvmnodes=$(get_lvm_deps "$nodes") || return 1
  367.  
  368.         # not backed by any dm-crypt nodes; stop here
  369.         if [ -z "$lvmnodes" ]; then
  370.             return 0
  371.         fi
  372.  
  373.         # It is a lvm device!
  374.         lastopts="lvm=$nodes"
  375.         nodes="$lvmnodes"
  376.     fi
  377.  
  378.     # Prepare to setup each node
  379.     count=$(echo "$nodes" | wc -w)
  380.     i=1
  381.     for node in $nodes; do
  382.         # Prepare the additional options
  383.         if [ $i -eq $count ]; then
  384.             if [ -z "$opts" ]; then
  385.                 opts="$lastopts"
  386.             elif [ -n "$lastopts" ]; then
  387.                 opts="$opts,$lastopts"
  388.             fi
  389.         fi
  390.  
  391.         # Get crypttab root options
  392.         if ! get_device_opts "$node" "$opts"; then
  393.             continue
  394.         fi
  395.         echo "$OPTIONS" >> "$DESTDIR/conf/conf.d/cryptroot"
  396.  
  397.         # If we have a keyscript, make sure it is included
  398.         if [ -n "$KEYSCRIPT" ]; then
  399.             if [ ! -d "$DESTDIR/lib/cryptsetup/scripts" ]; then
  400.                 mkdir -p "$DESTDIR/lib/cryptsetup/scripts"
  401.             fi
  402.  
  403.             if [ -e "/lib/cryptsetup/scripts/$KEYSCRIPT" ]; then
  404.                 copy_exec "/lib/cryptsetup/scripts/$KEYSCRIPT" /lib/cryptsetup/scripts >&2
  405.             elif [ -e "$KEYSCRIPT" ]; then
  406.                 copy_exec "$KEYSCRIPT" /lib/cryptsetup/scripts >&2
  407.             else
  408.                 echo "cryptsetup: WARNING: failed to find keyscript $KEYSCRIPT" >&2
  409.                 continue
  410.             fi
  411.         fi
  412.  
  413.         # Calculate needed modules
  414.         modules=$(get_device_modules $node | sort | uniq)
  415.         if [ -z "$modules" ]; then
  416.             echo "cryptsetup: WARNING: failed to determine cipher modules to load for $node" >&2
  417.             continue
  418.         fi
  419.         echo dm_mod
  420.         echo dm_crypt
  421.         echo "$modules"
  422.  
  423.         i=$(( $i + 1 ))
  424.     done
  425.  
  426.     return 0
  427. }
  428.  
  429. add_crypto_modules() {
  430.     local mod file altmod found genericfound
  431.     mod="$1"
  432.     found=""
  433.     genericfound=""
  434.  
  435.     if [ -z "$mod" ]; then
  436.         return 1
  437.     fi
  438.  
  439.     # We have several potential sources of modules (in order of preference):
  440.     #
  441.     #   a) /lib/modules/$VERSION/kernel/arch/$ARCH/crypto/$mod-$specific.ko
  442.     #   b) /lib/modules/$VERSION/kernel/crypto/$mod_generic.ko
  443.     #   c) /lib/modules/$VERSION/kernel/crypto/$mod.ko
  444.     #
  445.     # and (currently ignored):
  446.     #
  447.     #   d) /lib/modules/$VERSION/kernel/drivers/crypto/$specific-$mod.ko
  448.  
  449.     for file in $(find "$MODULESDIR/kernel/arch/" -name "$mod-*.ko"); do
  450.         altmod="${file##*/}"
  451.         altmod="${altmod%.ko}"
  452.         manual_add_modules "$altmod"
  453.         found="yes"
  454.     done
  455.  
  456.     for file in $(find "$MODULESDIR/kernel/crypto/" -name "${mod}_generic.ko"); do
  457.         altmod="${file##*/}"
  458.         altmod="${altmod%.ko}"
  459.         manual_add_modules "$altmod"
  460.         found="yes"
  461.         genericfound="yes"
  462.     done
  463.  
  464.     if [ -z "$genericfound" ]; then
  465.         for file in $(find "$MODULESDIR/kernel/crypto/" -name "${mod}.ko"); do
  466.             altmod="${file##*/}"
  467.             altmod="${altmod%.ko}"
  468.             manual_add_modules "$altmod"
  469.             found="yes"
  470.         done
  471.     fi
  472.  
  473.     if [ -z "$found" ]; then
  474.         return 1
  475.     fi
  476.  
  477.     return 0
  478. }
  479.  
  480. #
  481. # Begin real processing
  482. #
  483.  
  484. setup="no"
  485. rootdev=""
  486. resumedevs=""
  487.  
  488. # Find the root and resume device(s)
  489. if [ -r /etc/crypttab ]; then
  490.     rootdev=$(get_root_device)
  491.     if [ -z "$rootdev" ]; then
  492.         echo "cryptsetup: WARNING: could not determine root device from /etc/fstab" >&2
  493.     fi
  494.     resumedevs=$(get_resume_devices)
  495. fi
  496.  
  497. # Load the config opts and modules for each device
  498. for dev in $rootdev $resumedevs; do
  499.     if ! modules=$(add_device "$dev"); then
  500.         echo "cryptsetup: FAILURE: could not determine configuration for $dev" >&2
  501.         continue
  502.     fi
  503.     setup="yes"
  504.  
  505.     if [ "$MODULES" = "most" ]; then
  506.         archcrypto="$(find "$MODULESDIR/kernel/arch" -type d -name "crypto")"
  507.         if [ -n "$archcrypto" ]; then
  508.             copy_modules_dir "${archcrypto##*${MODULESDIR}/}"
  509.         fi
  510.         copy_modules_dir "kernel/crypto"
  511.     else
  512.         for mod in $modules; do
  513.             add_crypto_modules $mod
  514.         done
  515.     fi
  516. done
  517.  
  518. # With large initramfs, we always add a basic subset of modules
  519. if [ "$MODULES" != "dep" ]; then
  520.     for mod in aes cbc chainiv cryptomgr krng sha256 xts; do
  521.         add_crypto_modules $mod
  522.     done
  523. fi
  524.  
  525. # See if we need to add the basic components
  526. if [ "$MODULES" != "dep" ] || [ "$setup" = "yes" ]; then
  527.     for mod in dm_mod dm_crypt; do
  528.         manual_add_modules $mod
  529.     done
  530.  
  531.     copy_exec /sbin/cryptsetup
  532.     copy_exec /sbin/dmsetup
  533.     copy_exec /lib/cryptsetup/askpass
  534. fi
  535.  
  536. exit 0
  537.